/*******************************************************************************
* @Copyright : Shenzhen Hangshun Chip Technology R&D Co., Ltd 
* @Filename  : hk32c030xx_ts.c
* @brief     : This file provides firmware functions to manage the following 
  *          functionalities of the Temperature sensor (TS) peripheral:
  *           + Initialization and Configuration
  *           + Power saving
  *           + Temperature ALARM configuration
  *           + Temperature Calibration Configuration
  *           + Interrupts and flags management
* @Author   : AE Team  
* @Version  : V1.0.0/2022-11-28
* @log  V1.0.0
*
*******************************************************************************/


/* Includes ------------------------------------------------------------------*/
#include "hk32c030xx_ts.h"
#include "hk32c030xx_rcc.h"

/** @addtogroup HK32C030xx_StdPeriph_Driver
  * @{
  */

/** @defgroup TS   TS
  * @brief TS driver modules
  * @{
  @verbatim
================================================================================
                      ##### How to use this driver #####
================================================================================
    [..]
    (#) Enable the TS interface clock using 
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TEMPSEN, ENABLE);  
    (#) Configure the TS Clock, start up time, Sample delay, Average and external trigger
        using the TS_Init() function.
    (#) Activate the TS peripheral using TS_Cmd() function.

    *** TS configuration ***
    ============================================
    [..] 
    (+) To configure the TS features, use TS_Init() function.
    (+) To activate the Alarm mode, use the TS_ALARM_Cmd() function.
    (+) To activate the Average mode, use the TS_AVERAGE() function. 
    (+) To activate the external trigger mode, use the TS_TRGO_EXTSEL() functions.
    (+) To activate the calibration , use the TS_GetCalibrationFactor() functions.
    (+) To read the TS converted values, use the TS_GetConversionValue()
        function.
   @endverbatim 
 */
 
 
/** @defgroup TS_PERIPH_Constants  TS_PERIPH_Constants
  * @{
  */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

/* Calibration time out */
#define CALIBRATION_TIMEOUT       ((uint32_t)0x00000F00)
#define PWR_VREFINT_BUF        *(uint32_t *)((uint32_t)0x40007070)
#define TS_CAL        *(uint32_t *)((uint32_t)0x1ffff9a8)
/**
  * @}
  */ 
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup TS_Private_Functions    TS_Private_Functions
  * @{
  */

/** @defgroup TS_Group1 Initialization and Configuration functions
 *  @brief   Initialization and Configuration functions 
 *
@verbatim
 ===============================================================================
          ##### Initialization and Configuration functions #####
 ===============================================================================
    [..] This section provides functions allowing to:
        (+) Initialize and configure the TS Prescaler
        (+) External trigger Edge and source 
        (+) Enable or disable the TS peripheral
   
@endverbatim
  * @{
  */

/**
  * @brief  Deinitializes TS peripheral registers to their default reset values.
  * @retval None
  */
void TS_DeInit(void)
{
    /* Enable TS reset state */
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TEMPSEN, ENABLE);

    /* Release TS from reset state */
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TEMPSEN, DISABLE);
}

/**
  * @brief  Initializes the TS peripheral according to the specified parameters
  *         in the TS_InitStruct.
  * @note   This function is used to configure the global features of the TS ( 
  *         TS Clock, start up time, Alarm, Sample delay, Average and external trigger).   
  * @param  TS_InitStruct: pointer to an TS_InitTypeDef structure that contains 
  *         the configuration information for the specified TS peripheral.
  * @retval None
  */
void TS_Init(TS_InitTypeDef* TS_InitStruct)
{
  uint32_t tmpreg = 0;
	uint32_t tmpth = 0;
  /* Check the parameters */
  assert_param(IS_TS_CLOCKMODE(TS_InitStruct->TS_ClockDIV));
  assert_param(IS_TS_ANASTUP(TS_InitStruct->TS_ANASTUP));
  assert_param(IS_TS_SMPDLY(TS_InitStruct->TS_SMPDLY));
	assert_param(IS_TS_ALARM(TS_InitStruct->TS_ALARM));
  assert_param(IS_TS_EXT_TRIG_EDGE(TS_InitStruct->TS_EXTEN));
  assert_param(IS_TS_EXTERNAL_TRIG_CONV(TS_InitStruct->TS_EXTSEL));
  assert_param(IS_TS_AVERAGE(TS_InitStruct->TS_AVERAGE)); 

  /*---------------------------- TS CR Configuration ---------------------*/

  /* Set DIV[2:0] bits according to TS_ClockDIV value */
  /* Set ANASTUP[2:0] bits according to TS_ANASTUP value */
  /* Set SMPDLY[3:0] bits according to TS_SMPDLY value */
	/* Set ALARM[1:0] bits according to TS_ALARM value */
  /* Set EXTEN[1:0] bits according to TS_EXTEN value */
  /* Set EXTSEL[2:0] bits according to TS_EXTSEL value */
  /* Set AVERAGE[2:0] bits according to TS_AVERAGE value */
 
  tmpreg  |= (TS_InitStruct->TS_ClockDIV | TS_InitStruct->TS_ANASTUP | TS_InitStruct->TS_SMPDLY | TS_InitStruct->TS_ALARM |
							TS_InitStruct->TS_EXTEN | TS_InitStruct->TS_EXTSEL | TS_InitStruct->TS_AVERAGE);
	tmpth = ((TS_InitStruct->TS_HIGH_ALARM_TH)<<16) + TS_InitStruct->TS_LOW_ALARM_TH;
  /* Write to TS CR */
  TS->CR = tmpreg;
	/* Write to TS THR */
	TS->THR = tmpth;
	/*Open Vrefint buf */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
	PWR_VREFINT_BUF |= 0x0D;
	/*Set the Calibration data to the TS peripheral */
	TS->CALR =(uint8_t)TS_CAL;
}

/**
  * @brief  Fills each TS_InitStruct member with its default value.
  * @note   This function is used to initialize the global features of the TS ( 
  *         TS Clock, start up time, Alarm, Sample delay, Average and external trigger).
  * @param  TS_InitStruct: pointer to an TS_InitTypeDef structure which will 
  *         be initialized.
  * @retval None
  */
void TS_StructInit(TS_InitTypeDef* TS_InitStruct)
{
  /* Reset TS init structure parameters values */
  /* Initialize the TS_ClockDIV member */
  TS_InitStruct->TS_ClockDIV = TS_ClockDIV8;

   /* Initialize the TS_ANASTUP member */
  TS_InitStruct->TS_ANASTUP = TS_ANASTUP4;

  /* Initialize the TS_SMPDLY member */
  TS_InitStruct->TS_SMPDLY = TS_SMPDLY1;

  /* Initialize the TS_ALARM member */
  TS_InitStruct->TS_ALARM = TS_ALARM_Disable;	
	
  /* Initialize the TS_EXTEN member */
  TS_InitStruct->TS_EXTEN = TS_ExternalTrigConvEdge_None;

  /* Initialize the TS_EXTSEL member */
  TS_InitStruct->TS_EXTSEL = TS_ExternalTrigConv_T1_TRGO;	
	
  /* Initialize the TS_AVERAGE member */
  TS_InitStruct->TS_AVERAGE = TS_AVERAGE0;
}

/**
  * @brief  Set Analog start up time to the TS peripheral.
  * @param  TS_start_times: Analog start up time of the TS peripheral. 
  *         This parameter can be: TS_ANASTUP(1us to 1.875us).
  *            @arg TS_ANASTUP0 
  *            @arg TS_ANASTUP1 
  *            @arg ...
  *            @arg TS_ANASTUP7 
  * @retval None
  */
void TS_ANASTUP(uint32_t TS_start_times)
{
	uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_TS_ANASTUP(TS_start_times));
	
	tmpreg = TS->CR;
	tmpreg &= (~TS_CR_ANASTUP);
	tmpreg |=TS_start_times;
	/*Set Analog start up time to the TS peripheral */
	TS->CR = tmpreg;
}

/**
  * @brief  Set Sample delay time to the TS peripheral.
  * @param  TS_samp_dly: Sample delay timeof the TS peripheral. 
  *         This parameter can be: TS_SMPDLY(1 to 16 cycles).
  *            @arg TS_SMPDLY1 
  *            @arg TS_SMPDLY2 
  *            @arg ...
  *            @arg TS_SMPDLY16 
  * @retval None
  */
void TS_AMPDLY(uint32_t TS_samp_dly)
{
	uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_TS_SMPDLY(TS_samp_dly));
	
	tmpreg = TS->CR;
	tmpreg &= (~TS_CR_SMPDLY);
	tmpreg |=TS_samp_dly;
	/*Set Sample delay time to the TS peripheral */
	TS->CR = tmpreg;
}

/**
  * @brief  Set the trigger to start the TS peripheral.
  * @param  Trigger_edge: External trigger enable and polarity selection. 
  *         This parameter can be:
  *            @arg TS_ExternalTrigConvEdge_None: Sofware Trigger
  *            @arg TS_ExternalTrigConvEdge_Rising 
  *            @arg TS_ExternalTrigConvEdge_Falling
  *            @arg TS_ExternalTrigConvEdge_RisingFalling 
  * @param  Trigger_sources: External trigger selection. 
  *         This parameter can be: 
  *            @arg TS_ExternalTrigConv_T1_TRGO
  *            @arg TS_ExternalTrigConv_T1_CC4 
  *            @arg TS_ExternalTrigConv_T1_CC5
  *            @arg TS_ExternalTrigConv_T1_CC6 
  *            @arg TS_ExternalTrigConv_T2_TRGO
  *            @arg TS_ExternalTrigConv_T3_TRGO 
  *            @arg TS_ExternalTrigConv_T15_TRGO
  *            @arg TS_ExternalTrigConv_RTC_TRGO 
  * @retval None
  */
void TS_TRGO_EXTSEL(uint32_t Trigger_edge,uint32_t Trigger_sources)
{
	uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_TS_EXT_TRIG_EDGE(Trigger_edge));
	assert_param(IS_TS_EXTERNAL_TRIG_CONV(Trigger_sources));
	
	tmpreg = TS->CR;
	/*External trigger enable and polarity selection to the TS peripheral */
	tmpreg &= (~(TS_CR_EXTEN|TS_CR_EXTSEL));
	/*External trigger selection to the TS peripheral */
	tmpreg |=Trigger_edge|Trigger_sources;
	
	TS->CR = tmpreg;
}

/**
  * @brief  Set the High_threshold and Low_threshold to the TS peripheral.
  * @param  High_threshold: High temp threshold. 
  *         This parameter can be: 9 bits Temp data
  * @param  Low_threshold: Low temp threshold. 
  *         This parameter can be: 9 bits Temp data
  * @retval None
  */
void TS_THR_Config(uint16_t High_threshold,uint16_t Low_threshold)
{
	uint32_t tmpth = 0;
	/*Set the High_threshold and Low_threshold  to the TS peripheral */
	tmpth = (High_threshold<<16) + Low_threshold;
	/* Write to TS THR */
 	TS->THR = tmpth;
}

/**
  * @brief  Set the Calibration Temp to the TS peripheral.
  * @param  Cal_Temp: Calibration Temp. 
  *         This parameter can be: 9 bits Temp data
  * @retval None
  */
void TS_TESTMP_Config(uint16_t Cal_Temp)
{
	uint32_t Temp = 0;
	/*Set the Calibration Temp to the TS peripheral */
	Temp = (Cal_Temp<<16);
	/* Write to TS CALR */
 	TS->CALR = Temp;
}

/**
  * @brief  Set the Calibration to the TS peripheral.
  * @param  Calibration: Calibration data. 
  *         This parameter can be: 8 bits Temp data
  * @retval None
  */
void TS_CALR_Config(uint16_t Calibration)
{
	/* Write to TS CALR */
 	TS->CALR = Calibration;
}

/**
  * @brief  To get the TS converted values.
  * @retval The Data conversion value.
  */
uint16_t TS_GetConversionValue(void)
{
	/* read conversion value */
	return (uint16_t)TS->TMPR;
}

/**
  * @brief Calibration the TS peripheral.
  * @param  Cal_Temp: Calibration Temp. 
  *         This parameter can be: 9 bits Temp data
  * @retval None
  */
uint16_t TS_GetCalibrationFactor(uint16_t Cal_Temp)
{
	uint32_t tmpreg = 0;
	uint16_t CALR_data=0xFF;
	uint16_t CNT_CAL;
	/*reset Calibration data*/
	TS->CALR = 0;
	/*Set the Calibration Temp to the TS peripheral */
	TS->CALR = (Cal_Temp<<16);
	
	/* Write to TS CR  CALEN = 1, EN = 1*/
	TS->CR |= TS_CR_CALEN;
	TS->CR |= TS_CR_EN;
	/* wait TS ANARDY */
 	while((TS->ISR & TS_FLAG_ANARDY) == (uint32_t)RESET)
	{
		CNT_CAL++;
		__NOP ();
		if(CNT_CAL>CALIBRATION_TIMEOUT)
			break;
	}
	CNT_CAL = 0;
	TS->CR |= TS_CR_START;
 	while((TS->ISR & TS_FLAG_CALDN) == (uint32_t)RESET)
	{
		CNT_CAL++;
		__NOP ();
		if(CNT_CAL>CALIBRATION_TIMEOUT)
			break;
	}	
	CALR_data = (uint16_t)TS->CALR;
	tmpreg = TS->CR;
	tmpreg &= (~TS_CR_EN);
	TS->CR = tmpreg;
	tmpreg = TS->CR;
	tmpreg &= (~TS_CR_CALEN);	
	TS->CR = tmpreg;
	return CALR_data;
}
/**
  * @brief  Set temperature Alarm to the TS peripheral.
  * @param  TS_ALARM: temperature Alarm. 
  *         This parameter can be: 
  *            @arg TS_ALARM_Disable 
  *            @arg TS_ALARM_Low_EN 
  *            @arg TS_ALARM_High_EN
  *            @arg TS_ALARM_Low_High_BothEN 
  * @retval None
  */
void TS_ALARM_Cmd(uint32_t TS_ALARM)
{
	uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_TS_ALARM(TS_ALARM));
	
	tmpreg = TS->CR;
	tmpreg &= (~TS_CR_ALARM);
	tmpreg |=TS_ALARM;
	/*Set temperature Alarm to the TS peripheral */
	TS->CR = tmpreg;
}

/**
  * @brief  Set Clock Division to the TS peripheral.
  * @param  TS_Clock_DIV: Clock Division. 
  *         This parameter can be: 
  *            @arg TS_ClockDIV0 
  *            @arg TS_ClockDIV2 
  *            @arg TS_ClockDIV4
  *            @arg TS_ClockDIV8 
  *            @arg TS_ClockDIV16 
  * @retval None
  */
void TS_SetClock(uint32_t TS_Clock_DIV)
{
	uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_TS_CLOCKMODE(TS_Clock_DIV));
	
	tmpreg = TS->CR;
	tmpreg &= (~TS_Clock_DIV);
	tmpreg |=TS_Clock_DIV;
	/*Set Clock_DIV to the TS peripheral */
	TS->CR = tmpreg;
}

/**
  * @brief  Set Average_times (oversampling) to the TS peripheral.
  * @param  TS_Average_times: oversampling times. 
  *         This parameter can be: 
  *            @arg TS_AVERAGE0 
  *            @arg TS_AVERAGE2 
  *            @arg TS_AVERAGE4
  *            @arg TS_AVERAGE8 
  *            @arg TS_AVERAGE16 
  * @retval None
  */
void TS_AVERAGE(uint32_t TS_Average_times)
{
	uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_TS_AVERAGE(TS_Average_times));
	
	tmpreg = TS->CR;
	tmpreg &= (~TS_Average_times);
	tmpreg |=TS_Average_times;
	/*Set Average_times to the TS peripheral */
	TS->CR = tmpreg;
}

/**
  * @brief  Enables or disables the specified TS peripheral.
  * @param  NewState: new state of the TS peripheral. 
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void TS_Cmd(FunctionalState NewState)
{
	uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    /* Set the EN bit to Enable the TS peripheral */
    TS->CR |= (uint32_t)TS_CR_EN;
  }
  else
  {
		tmpreg = TS->CR;
		tmpreg &= (~TS_CR_EN);
    /* Set the ADDIS to Disable the TS peripheral */
    TS->CR = tmpreg;
  }
}

/**
  * @brief  Start the TS peripheral.
  * @retval None
  */
void TS_Start(void)
{
    /* Set the START bit to Start the TS peripheral */
    TS->CR |= TS_CR_START;
}



/**
  * @}
  */ 

/** @defgroup TS_Group2 Interrupts and flags management functions
 *  @brief   Interrupts and flags management functions.
 *
@verbatim
 ===============================================================================
          ##### Interrupts and flags management functions #####
 ===============================================================================
    [..] This section provides functions allowing to configure the TS Interrupts 
         and get the status and clear flags and Interrupts pending bits.
  
    [..] The TS provide 6 Interrupts sources and 11 Flags which can be divided into 

  *** Flags for TS status ***
	======================================================
		[..]
				(+)Flags :
					 (##) TS_FLAG_ANARDY : This flag is set after TS EN,
																specifies the interrupt source for TS ready event.
					 (##) TS_FLAG_OVRTRIGO : This flag is set by External overrun,
																specifies the interrupt source for TS OVRTRIGO event.
					 (##) TS_FLAG_HIGH : This flag is set once the High temp alarm,
																specifies the interrupt source for TS High temp alarm event.
					 (##) TS_FLAG_LOW : This flag is set once the Low temp alarm,
																specifies the interrupt source for TS Low temp alarm event.
					 (##) TS_FLAG_SENDN : This flag is set once the conversion is complete,
																specifies the interrupt source for TS conversion is complete event.
					 (##) TS_FLAG_CALDN : This flag is set once the calibration is complete,
																specifies the interrupt source for TS calibration is complete event.
@endverbatim
  * @{
  */

/**
  * @brief  Enables or disables the specified TS interrupts.
  * @param  TS_IT: specifies the TS interrupt sources to be enabled or disabled.
  *          This parameter can be one of the following values:
  *            @arg TS_IT_HIGH: TS High temp interrupt
  *            @arg TS_IT_LOW: TS Low temp interrupt 
  *            @arg TS_IT_SENDN: End of conversion interrupt
  *            @arg TS_IT_OVRTRIGO: OVRTRIGO interrupt
  *            @arg TS_IT_CALDN: End of calibration interrupt
  * @param  NewState: new state of the specified TS interrupts.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void TS_ITConfig(uint32_t TS_IT, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  assert_param(IS_TS_GET_IT(TS_IT));

  if (NewState != DISABLE)
  {
    /* Enable the selected TS interrupts */
    TS->IER |= TS_IT;
  }
  else
  {
    /* Disable the selected TS interrupts */
    TS->IER &= (~(uint32_t)TS_IT);
  }
}

/**
  * @brief  Checks whether the specified TS flag is set or not.
  * @param  TS_FLAG: specifies the flag to check. 
  *          This parameter can be one of the following values:
  *            @arg TS_FLAG_OVRTRIGO: Overrun flag 
  *            @arg TS_FLAG_SENDN: End of conversion flag
  *            @arg TS_FLAG_ANARDY: TS Ready flag
  *            @arg TS_FLAG_HIGH: TS High temp flag 
  *            @arg TS_FLAG_LOW: TS Low temp flag 
  *            @arg TS_FLAG_CALDN: TS Calibration flag
  * @retval The new state of TS_FLAG (SET or RESET).
  */
FlagStatus TS_GetFlagStatus(uint32_t TS_FLAG)
{
  FlagStatus bitstatus = RESET;
  uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_TS_GET_FLAG(TS_FLAG));
	if(TS_FLAG == TS_FLAG_ANARDY)
	{
		tmpreg = TS->CR;
	}
	else
	{
		tmpreg = TS->ISR;
	}
  /* Check the status of the specified TS flag */
  if ((tmpreg & TS_FLAG) != (uint32_t)RESET)
  {
    /* TS_FLAG is set */
    bitstatus = SET;
  }
  else
  {
    /* TS_FLAG is reset */
    bitstatus = RESET;
  }
  /* Return the TS_FLAG status */
  return  bitstatus;
}

/**
  * @brief  Clears the TS pending flags.
  * @param  TS_CLEAR_FLAG: specifies the flag to clear. 
  *          This parameter can be any combination of the following values:
  *            @arg TS_FLAG_CLEAR_OVRTRIGO: Overrun flag 
  *            @arg TS_FLAG_CLEAR_SENDN: End of conversion flag
  *            @arg TS_FLAG_CLEAR_HIGH: TS High temp flag 
  *            @arg TS_FLAG_CLEAR_LOW: TS Low temp flag 
  *            @arg TS_FLAG_CLEAR_CALDN: TS Calibration flag
  * @retval None
  */
void TS_ClearFlag(uint32_t TS_CLEAR_FLAG)
{
  /* Check the parameters */
  assert_param(IS_TS_CLEAR_FLAG(TS_CLEAR_FLAG));

  /* Clear the selected TS flags */
  TS->ISR = (uint32_t)TS_CLEAR_FLAG;
}


/**
  * @}
  */ 

/**
  * @}
  */ 
 /**
  * @}
  */ 

 /**
  * @}
  */
